home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_ImportAdv / rotateprocs.c < prev    next >
Text File  |  1992-12-19  |  6KB  |  219 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34. *    rotateprocs.c
  35. *
  36. *    This file contains procedure that perform operations
  37. *    on rotated rectangles and points.
  38. *
  39. *    Note: the angle in the procedures below should be expressed
  40. *    in radians and not degrees.
  41. */
  42.  
  43. #import <appkit/graphics.h>
  44. #import <appkit/nextstd.h>
  45. #import <math.h>
  46.  
  47. /*
  48. *    Takes the point passed in, rotates it around the point
  49. *    at the angle given and returns the new point.
  50. *    The new point replaces the old one and its address
  51. *    is returned as the return value.
  52. */
  53. NXPoint *RotatePoint(NXPoint *aPoint, NXPoint *cPoint, float angle)
  54. {
  55.     float        d, dx, dy;
  56.  
  57.     float        ang;
  58.  
  59.     if (aPoint && cPoint && angle != 0)
  60.     {
  61.         dx = aPoint->x - cPoint->x;
  62.         dy = aPoint->y - cPoint->y;
  63.  
  64.         *aPoint = *cPoint;
  65.         d = sqrt(dx * dx + dy * dy);
  66.         if (d != 0.0)
  67.         {
  68.             ang = angle + (float) atan2(dy, dx);
  69.             aPoint->x += d * cos(ang);
  70.             aPoint->y += d * sin(ang);
  71.         }
  72.     }
  73.  
  74.     return aPoint;
  75. }
  76.  
  77. /*
  78. *    Checks whether the point passed in lies in the rectangle
  79. *    rotated about its lower left vertice at the angle provided.
  80. *    Returns either YES or NO. Assumes an unflipped 
  81. *    coordinate system.
  82. */
  83. BOOL MouseInRotatedRect(NXPoint *aPoint, NXRect *aRect, float angle)
  84. {
  85.     NXPoint        pt;
  86.  
  87.     if (aRect && aPoint)
  88.     {
  89.         pt = *aPoint;
  90.         RotatePoint(&pt, &aRect->origin, -angle);
  91.  
  92.         return NXMouseInRect(&pt, aRect, NO);
  93.     }
  94.     else
  95.         return NO;
  96. }
  97.  
  98. /*
  99. *    This procedure takes the unrotated rectangle, bRect,
  100. *    rotates it around the point, cPoint, at the angle, angle,
  101. *    and places the new bounding box that encloses the
  102. *    rotated rectangle in the rectangle aRect. The address
  103. *    of the new rectangle is returned as the return value.
  104. *
  105. *    Figuring the new width and height is relatively
  106. *    straight-forward. Just take the sin and cos of  the
  107. *    old width and height.
  108. *
  109. *    Figuring the new origin is a bit different. The vertices
  110. *    for the lower x and lower y coordinates are chosen
  111. *    based on the angle to rotate. Their positions in the rotated
  112. *    spaced are calculated and subtracted from the center point.
  113. */
  114. NXRect *RotateRectBounds(NXRect *aRect, const NXRect *bRect, NXPoint *cPoint, float angle)
  115. {
  116.     float            dx, dy, dxx, dxy, dyx, dyy;
  117.  
  118.     double        cosa, sina;
  119.     
  120.     if (aRect  && bRect && cPoint)
  121.     {
  122.         if (angle != 0)
  123.         {
  124.             cosa = cos(angle);
  125.             sina = sin(angle);
  126.  
  127.             dyx = dxx = bRect->origin.x - cPoint->x;
  128.             dyy = dxy = bRect->origin.y - cPoint->y;
  129.  
  130.             if (cosa > 0)
  131.             {
  132.                 if (sina > 0)
  133.                     dxy += bRect->size.height;
  134.                 else
  135.                     dyx += bRect->size.width;        
  136.             }
  137.             else
  138.             {
  139.                 if (sina > 0)
  140.                 {
  141.                     dxx += bRect->size.width;
  142.                     dyy = dxy = dxy + bRect->size.height;
  143.                 }
  144.                 else
  145.                 {
  146.                     dyx = dxx = dxx + bRect->size.width;
  147.                     dyy += bRect->size.height; 
  148.                 }
  149.             }
  150.  
  151.             aRect->origin = *cPoint;
  152.  
  153.             dx = sqrt(dxx * dxx + dxy * dxy);
  154.             if (dx != 0.0)
  155.                 aRect->origin.x += (float) dx * cos(angle + atan2(dxy, dxx));
  156.             dy = sqrt(dyx * dyx + dyy * dyy);
  157.             if (dy != 0.0)
  158.                 aRect->origin.y += (float) dy * sin(angle + atan2(dyy, dyx));
  159.  
  160.             aRect->size.width = (float) (ABS(bRect->size.width * cosa) +
  161.                         ABS(bRect->size.height * sina));
  162.             aRect->size.height = (float) (ABS(bRect->size.width * cos(M_PI_2 - angle)) +
  163.                         ABS(bRect->size.height * sin(M_PI_2 - angle)));
  164.         }
  165.         else
  166.             *aRect = *bRect;
  167.     }
  168.  
  169.     return aRect;
  170. }
  171.  
  172. /*
  173. *    This procedure takes two rectangles and an angle.
  174. *    It checks if the second rectangle rotated about its origin
  175. *    at the given angle intersects the first rectangle. The
  176. *    first rectangle is unrotated. 
  177. *
  178. *    It checks for intersection by getting the frame for the rotated
  179. *    rectangle and then checking the intersection.
  180. */
  181. BOOL IntersectsRotatedRect(NXRect *aRect, NXRect *bRect, float angle)
  182. {
  183.     NXRect    rect;
  184.  
  185.     if (aRect && bRect)
  186.     {
  187.         if (angle != 0.0)
  188.         {
  189.             RotateRectBounds(&rect, bRect, &bRect->origin, angle);
  190.             bRect = ▭
  191.         }
  192.  
  193.         return NXIntersectsRect(aRect, bRect);
  194.     }
  195.  
  196.     return NO;
  197. }
  198.  
  199. /*
  200. *    This procedure takes two points and constrains the first
  201. *    point to the nearest 15% interval.
  202. */
  203. void ConstrainPointToAngle(NXPoint *aPoint, NXPoint *cPoint, float angle)
  204. {
  205.     float        d, dx, dy, a;
  206.  
  207.     dx = aPoint->x - cPoint->x;
  208.     dy = aPoint->y - cPoint->y;
  209.     d = sqrt(dx*dx + dy*dy);
  210.  
  211.     if (d != 0.0)
  212.     {
  213.         a = rint(atan2(dy, dx) / angle) * angle;
  214.         aPoint->x = (float) cPoint->x + d * cos(a);
  215.         aPoint->y = (float) cPoint->y + d * sin(a);
  216.     }
  217. }
  218.  
  219.